﻿package taurus.client.io;

import com.taurus.core.util.*;

import taurus.client.SocketCode;

/**
 * Socket核心基类
 * @author daixiwei	daixiwei15@126.com
 *
 */
public abstract class ISocket {
	protected static final Logger	logger	= Logger.getLogger(ISocket.class);
	SocketEngine						_engine;
	/**
	 * 当前socket状态
	 */
	public volatile SocketState		state	= SocketState.Disconnected;
	/**
	 * 服务器地址
	 */
	protected String				serverAddress;
	/**
	 * 服务器端口
	 */
	protected int					serverPort;

	/**
	 * 网络链接状态
	 * @return
	 */
	public boolean isConnected() {
		return state == SocketState.Connected;
	}

	public ISocket(SocketEngine peerBase) {
		if (peerBase == null) {
			throw new RuntimeException("Can't init without peer");
		}
		this._engine = peerBase;
	}

	public boolean connect() {
		boolean result;
		if (state != SocketState.Disconnected) {
			logger.error("Calling connect when the socket is not disconnected");
			result = false;
		} else if (_engine == null) {
			result = false;
		} else if (!tryParseAddress(_engine.getServerAddress())) {
			logger.error("Failed parsing address: " + _engine.getServerAddress());
			result = false;
		} else {
			result = true;
		}
		return result;
	}

	/**
	 * 断开连接
	 * @return
	 */
	public abstract boolean disconnect();

	/**
	 * 发送流数据
	 * @param data
	 * @return
	 */
	public abstract boolean send(byte[] data);

	protected void handleException(SocketCode statusCode) {
		state = SocketState.Disconnecting;
		_engine.enqueueStatusCallback(statusCode);
		_engine.enqueueActionForDispatch(new Runnable() {
			@Override
			public void run() {
				disconnect();
			}
		});
	}

	/**
	 * 解析网络地址
	 * @param addressAndPort
	 * @param address
	 * @param port
	 * @return
	 */
	protected boolean tryParseAddress(String addressAndPort) {
		boolean result = true;
		if (StringUtil.isEmpty(addressAndPort)) {
			result = false;
		} else {
			int num = addressAndPort.lastIndexOf(':');
			if (num <= 0) {
				result = false;
			} else if (addressAndPort.indexOf(':') != num && (!addressAndPort.contains("[") || !addressAndPort.contains("]"))) {
				result = false;
			} else {
				serverAddress = addressAndPort.substring(0, num);
				String s = addressAndPort.substring(num + 1);
				try {
					serverPort = Integer.parseInt(s);
				} catch (Exception e) {
					result = false;
				}
			}
		}
		return result;
	}

}
